package com.sac.approval.controller;

import com.sac.approval.domain.ApprovalDO;
import com.sac.approval.domain.ApprovalLineDO;
import com.sac.approval.domain.AttachmentDO;
import com.sac.approval.domain.DelegateMappingDO;
import com.sac.approval.enums.ApprovalLineStatusEnum;
import com.sac.approval.enums.ApprovalStatusEnum;
import com.sac.approval.service.*;
import com.sac.approval.vo.ApItemVO;
import com.sac.common.annotation.AuthToken;
import com.sac.common.utils.*;
import com.sac.system.domain.UserDO;
import com.sac.system.service.UserService;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.context.Context;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 审批处理
 * @author xiaodong
 * @date 2018年9月13日 上午11:21:13
 * @desc 提交，取消，处理，查询
 */
@RestController
@RequestMapping("/approval")
public class ApprovalController {

	@Autowired
	private EmailService emailService;

	@Autowired
	private ApprovalService approvalService;

	@Autowired
	private ApprovalLineService approvalLineService;

	@Autowired
	private ApprovalTemplateService approvalTemplateService;

	@Autowired
	private AttachmentService attachmentService;

	@Autowired
	private UserService userService;

	@Autowired
	private ApprovalQueryService approvalQueryService;

	@Autowired
	private DelegateMappingService delegateMappingService;

	@AuthToken
	@PostMapping("/create")
	public Object createApproval(@RequestParam Map<String, Object> params) {
		try {
			System.out.println("createApproval:" + ResourceUtils.getURL("classpath:upload").getPath());
			List<String> users = new ArrayList<String>();
			users.add(ShiroUtils.getUser().getEmpId().toString());
			WebSocketUtil.pushPendingNotification("71002651", "测试一下下哈哈哈");
			//webSocketUtils.pushCastNotification("测试一下下哈哈哈");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		return R.ok();
	}

	/**
	 * 发送邮件-测试方法
	 * @param params
	 * @return
	 */
	@PostMapping("/sendMail")
	public Object sendMail(@RequestParam Map<String, Object> params) {
		System.out.println("sendMail");
		emailService.sendSimpleMail("kang.li@hp.com", "测试邮件", "这是一封测试邮件");
		return R.ok();
	}

	/**
	 * 发送邮件
	 * @param params
	 * @return
	 */
	@PostMapping("/sendTemplateMail")
	public Object sendTemplateMail(@RequestParam Map<String, Object> params) {
		Context context = new Context();
		context.setVariable("message", "这里是测试的模板消息");
		emailService.sendTemplateMail("liu.xiaodong@hp.com", "这真的只是一封测试邮件", context, "mail/mailTemplate", null);
		return R.ok();
	}

	/**
	 * 创建审批
	 * @param apItemVO
	 * @return
	 */
	@AuthToken
	@PostMapping("/submit/general")
	public Object general(ApItemVO apItemVO) {
		Date date = new Date();
		//master
		ApprovalDO app = new ApprovalDO();
		app.setAppId(DateFormatUtils.format(new Date(),"yyyyMMddhhmmssSSS"));
		app.setTitle(apItemVO.getApTtl());
		app.setContent(apItemVO.getTxtClobcn());
		app.setContType(apItemVO.getTxtTypeCd());
		app.setCharSet(apItemVO.getChsetCd());
		app.setSecretType(apItemVO.getApDocSecuTypeCd());
		app.setNotifyType(apItemVO.getNtfTypeCd());
		app.setUrgentType(apItemVO.getUrgYn());
		app.setCreateTime(date);
		app.setCreateUser(ShiroUtils.getEmpId().toString());
		app.setStatus(ApprovalStatusEnum.PENDING.getValue());
		//审批line
		List<ApprovalLineDO> appLines = new ArrayList<ApprovalLineDO>();
		if(apItemVO.getAapTaplnVOList()!=null){
			Arrays.asList(apItemVO.getAapTaplnVOList()).forEach(receiver -> {

				ApprovalLineDO appLine = new ApprovalLineDO();
				appLine.setAppId(app.getAppId());
				appLine.setHandleType(Integer.parseInt(receiver.getApRlCd()));
				if("0".equals(receiver.getApSeq())){
					appLine.setReceiptTime(date);
					appLine.setReadTime(date);
					appLine.setHandleTime(date);
					appLine.setRemark(apItemVO.getRemark());
				}
				appLine.setReceiverEpid(receiver.getApRelrEpid());
				appLine.setReceiverMail(receiver.getAprelrmailaddr());
				appLine.setSeq(Integer.parseInt(receiver.getApSeq()));
				appLine.setStatus(ApprovalLineStatusEnum.PENDING.getValue());
				appLine.setArbPmtYn(receiver.getArbPmtYn());
				appLine.setTxtMdfyPmtYn(receiver.getTxtMdfyPmtYn());
				appLine.setPathMdfyPmtYn(receiver.getPathMdfyPmtYn());
				appLine.setIsDelete("N");
				appLines.add(appLine);
			});
		}

		//附件
		List<AttachmentDO> attachments = new ArrayList<AttachmentDO>();
		if(apItemVO.getFiles()!=null) {
			Arrays.asList(apItemVO.getFiles()).forEach(file -> {

				String originFileName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("\\")+1).split("\\?")[0];

				String fileName = FileUtil.renameToUUID(originFileName);

				AttachmentDO attachment = new AttachmentDO();
				attachment.setAppId(app.getAppId());
				attachment.setFileName(fileName);
				attachment.setFileOriginName(originFileName);
				if(file.getSize() == 0L){
					attachment.setFileSize(Long.parseLong(file.getOriginalFilename().split("\\?").length > 1 ? file.getOriginalFilename().split("\\?")[1] : "0" ));
				}else {
					attachment.setFileSize(file.getSize());// B
				}
				attachment.setFileType(file.getContentType());

				attachments.add(attachment);
				try {
					// 上传附件
					//FileUtil.uploadFile(file.getBytes(), ResourceUtils.getURL("classpath:upload").getPath()+ File.separator,fileName);
					SftpUtil.uploadFile(file.getBytes(),fileName);
				} catch (Exception e) {
					e.printStackTrace();
					throw new BDException("文件上传失败");
				}
			});
		}
		//保存信息
		approvalService.createApproval(app, appLines,attachments);

		//获取后面的审批人列表
        List<ApprovalLineDO> pendingLineList = approvalQueryService.getPendingApproverList(app.getAppId());

		// 异步发送邮件和通知
		approvalService.pushPendingNotification(pendingLineList,app);
		approvalService.sendEmail(pendingLineList,app);
		return R.ok();
	}


	/**
	 * 更新审批邮件的分类
	 * @param params
	 * @return
	 */
	@AuthToken
	@PutMapping("/updateCategory")
	public Object updateCategory(@RequestParam Map<String, Object> params) {
		ApprovalLineDO appLine = new ApprovalLineDO();
		appLine.setAppLineId(Long.parseLong(params.get("appLineId").toString()));
		appLine.setCategory(params.get("category").toString());
		approvalLineService.update(appLine);
		return R.ok();
	}

	/**
	 * 更新审批邮件的路径及正文
	 * @param apItemVO
	 * @return
	 */
	@AuthToken
	@PostMapping("/updateApproval")
	public Object updateApp(ApItemVO apItemVO) {
		Date date = new Date();
		//master
		ApprovalDO app = new ApprovalDO();
		app.setAppId(apItemVO.getAppId());
		app.setTitle(apItemVO.getApTtl());
		app.setContent(apItemVO.getTxtClobcn());
		app.setContType(apItemVO.getTxtTypeCd());
		app.setCharSet(apItemVO.getChsetCd());
		app.setSecretType(apItemVO.getApDocSecuTypeCd());
		app.setNotifyType(apItemVO.getNtfTypeCd());
		app.setUrgentType(apItemVO.getUrgYn());
		app.setStatus(ApprovalStatusEnum.PENDING.getValue());
		//审批line
		List<ApprovalLineDO> appLines = new ArrayList<ApprovalLineDO>();
		if(apItemVO.getAapTaplnVOList()!=null){
			Arrays.asList(apItemVO.getAapTaplnVOList()).forEach(receiver -> {

				ApprovalLineDO appLine = new ApprovalLineDO();
				appLine.setAppId(apItemVO.getAppId());
				appLine.setHandleType(Integer.parseInt(receiver.getApRlCd()));
				appLine.setReceiverEpid(receiver.getApRelrEpid());
				appLine.setReceiverMail(receiver.getAprelrmailaddr());
				appLine.setSeq(Integer.parseInt(receiver.getApSeq()));
				appLine.setStatus(ApprovalLineStatusEnum.PENDING.getValue());
				appLine.setArbPmtYn(receiver.getArbPmtYn());
				appLine.setTxtMdfyPmtYn(receiver.getTxtMdfyPmtYn());
				appLine.setPathMdfyPmtYn(receiver.getPathMdfyPmtYn());
				appLine.setPreReadTime(receiver.getPreReadTime());
				appLine.setReceiptTime(receiver.getReceiptTime());
				appLine.setReadTime(receiver.getReadTime());
				appLine.setHandleTime(receiver.getHandleTime());
				appLine.setIsDelete("N");
				appLine.setRemark(receiver.getRemark());
				appLine.setChangeLineYn(receiver.getChangeLineYn()) ;
				appLine.setChangeTextYn(receiver.getChangeTextYn());

				appLines.add(appLine);
			});
		}

		//附件
		List<AttachmentDO> attachments = new ArrayList<AttachmentDO>();
		if(apItemVO.getFiles()!=null) {
			Arrays.asList(apItemVO.getFiles()).forEach(file -> {
				String fileName = FileUtil.renameToUUID(file.getOriginalFilename().split("\\?")[0]);

				AttachmentDO attachment = new AttachmentDO();
				attachment.setAppId(apItemVO.getAppId());
				attachment.setFileName(fileName);
				attachment.setFileOriginName(file.getOriginalFilename().split("\\?")[0]);
				if(file.getSize() == 0L){
					attachment.setFileSize(Long.parseLong(file.getOriginalFilename().split("\\?")[1]));
				}else {
					attachment.setFileSize(file.getSize());
				}
				attachment.setFileType(file.getContentType());
				attachments.add(attachment);
				try {
					// 上传附件
					//FileUtil.uploadFile(file.getBytes(), ResourceUtils.getURL("classpath:upload").getPath()+ File.separator,fileName);
					SftpUtil.uploadFile(file.getBytes(),fileName);
				} catch (Exception e) {
					e.printStackTrace();
					throw new BDException("文件上传失败");
				}
			});
		}
		//保存信息
		approvalService.updateApproval(app, appLines,attachments);

//		//获取后面的审批人列表
//		List<ApprovalLineDO> pendingLineList = approvalQueryService.getPendingApproverList(app.getAppId());
//		pendingLineList.forEach(line -> line.setReceiptTime(date));
//
//		// 异步发送邮件和通知
//		approvalService.pushPendingNotification(pendingLineList,app);
//		approvalService.sendEmail(pendingLineList,app);
		return R.ok();
	}

	/**
	 * 处理审批
	 * 
	 * @param params
	 * @return
	 */
	@AuthToken
	@PostMapping("/handle")
	public Object handle(@RequestParam Map<String, Object> params) {
		switch(params.get("type").toString()) {
			case "approve":
			    handleApprove(params);
				break;
			case "consent":
			    handleApprove(params);
				break;
			case "reject":
			    handleReject(params);
				break;
			case "arbi":
			    handleArbi(params);
				break;
		}
		
		return R.ok();
	}

    /**
     * 批准
     * @param params
     */
	private void handleApprove(Map<String, Object> params) {
		approvalService.handleApprove(params);
	}

    /**
     * 协议
     * @param params
     */
	private void handleConsent(Map<String, Object> params) {
		approvalService.handleApprove(params);
	}

    /**
     * 驳回
     * @param params
     */
	private void handleReject(Map<String, Object> params) {
        //异步发送邮件
		approvalService.handleReject(params);
	}

    /**
     * 特批
     * @param params
     */
	private void handleArbi(Map<String, Object> params) {
		//判断简单/平行审批
		//如果是简单审批，结束流程（修改line状态，修改其他人审批状态为已审批，修改master状态）
		//如果是平行审批，则跳出此节点（修改同级别节点状态为已审批），进入下一节点继续审批
		//发送邮件通知
		approvalService.handleArbi(params);
	}
	
	
	@AuthToken
	@PostMapping("/submit/withAttach")
	public Object withAttach(@RequestParam Map<String, Object> params) {

		return R.ok();
	}

	@AuthToken
	@PostMapping("/statusInquiry/getListByUserKey")
	public Object getListByUserKey(@RequestParam Map<String, Object> params) {

		return R.ok();
	}

	@AuthToken
	@PostMapping("/statusInquiry/getStatusByMisId")
	public Object getStatusByMisId(@RequestParam Map<String, Object> params) {

		return R.ok();
	}

	@AuthToken
	@PostMapping("/statusInquiry/getRevisionByMisId")
	public Object getRevisionByMisId(@RequestParam Map<String, Object> params) {

		return R.ok();
	}

	/**
	 * 取消审批： 只有那些正在进行的文件才能被取消; 已完成的批准文件的状态（已完成，拒绝，取消，任意批准）无法更改
	 * 
	 * @param appId
	 * @return
	 */
	@AuthToken
	@PutMapping("/cancel")
	public Object cancel(String appId,String remark) {
		ApprovalDO approval = approvalQueryService.getApproval(appId);
		approval.setStatus(ApprovalStatusEnum.CANCELED.getValue());
		ApprovalLineDO draft = approvalQueryService.getApprovalDraft(appId);
		draft.setRemark(remark);
		draft.setHandleTime(new Date());
		approvalService.cancelSubmission(approval,draft);
		return R.ok();
	}

	/**
	 * 删除审批
	 *
	 * @param appLineId
	 * @return
	 */
	@AuthToken
	@DeleteMapping("/delete/{appLineId}")
	public Object delete(@PathVariable String appLineId) {
		ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
		line.setIsDelete("Y");
		approvalLineService.update(line);
		return R.ok();
	}

	/**
	 * 批量删除审批
	 *
	 * @param appLineIds
	 * @return
	 */
	@AuthToken
	@PostMapping("/batchDelete")
	public Object batchDelete(@RequestParam String[] appLineIds) {
		List<ApprovalLineDO> lineList = new ArrayList<>();
		Arrays.asList(appLineIds).forEach(appLineId->{
			ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
			line.setIsDelete("Y");
			lineList.add(line);
		});

		approvalLineService.batchUpdate(lineList);
		return R.ok();
	}

	/**
	 * 删除草稿
	 *
	 * @param appTemplateId
	 * @return
	 */
	@AuthToken
	@DeleteMapping("/deleteTemplate/{appTemplateId}")
	public Object deleteTemplate(@PathVariable String appTemplateId) {
		approvalTemplateService.remove(appTemplateId);
		return R.ok();
	}

	@GetMapping("/preview/{fileOriginName:.+}*/{fileName:.+}*")
    public void preview(HttpServletResponse response, @PathVariable String fileOriginName, @PathVariable String fileName) throws Exception {
		SftpUtil.preview(response,fileOriginName,fileName);
	}

    @GetMapping("/download/{fileOriginName:.+}*/{fileName:.+}*")
    public void download(HttpServletResponse response, @PathVariable String fileOriginName, @PathVariable String fileName) throws Exception {
        //SftpUtil.downloadFile(fileName,"c://test/"+fileOriginName);
		try {
			SftpUtil.download(response, fileOriginName, fileName);
		}catch(Exception e){
			WebSocketUtil.pushPendingNotification(ShiroUtils.getEmpId(), "网络状况较差，文件可能无法成功下载！");
		}
    }

    @PutMapping("/readApproval/{appLineId}")
    public Object readApproval(@PathVariable String appLineId) {
        ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
        line.setReadTime(new Date());
        approvalLineService.update(line);
        return R.ok();
    }

    @PutMapping("/preReadApproval/{appLineId}")
    public Object preReadApproval(@PathVariable String appLineId) {
        ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
        line.setPreReadTime(new Date());
        approvalLineService.update(line);
        return R.ok();
    }

    @PutMapping("/saveLocalPassword/{password}")
    public Object saveLocalPassword(@PathVariable String password) {
        UserDO user = ShiroUtils.getUser();
        password = MD5Utils.simpleEncrypt(user.getEmpNm(), password);
        user.setPassword(password);
        userService.update(user);
        return R.ok().put("hpUser",user);
    }

    @PutMapping("/saveExternalMail")
    public Object saveExternalMail(String externalMail) {
        UserDO user = ShiroUtils.getUser();
        user.setExternalMail(externalMail);
        userService.update(user);
        return R.ok().put("hpUser",user);
    }

    @PostMapping("/saveDelegateMapping")
    public Object saveDelegateMapping(@RequestParam Map<String, Object> params) throws ParseException {
		String agentUserId = params.get("agentUserId").toString();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		String startDateStr = params.get("startDate").toString();
		String endDateStr = params.get("endDate").toString();
		String option = params.get("option").toString();

		//日期区间 [startDate,endDate),不包含后者
		String today = DateFormatUtils.format(new Date(),"yyyy/MM/dd HH:mm:ss");
		if(today.split("\\s+")[0].equals(startDateStr)){
			startDateStr = today;
		}

		Date endDate = sdf.parse(endDateStr);
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(endDate);
		calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
		endDate=calendar.getTime(); //这个时间就是日期往后推一天的结果

		DelegateMappingDO delegate = delegateMappingService.get(ShiroUtils.getEmpId(),agentUserId);
		if(delegate == null){
			delegate = new DelegateMappingDO();
			delegate.setUserId(ShiroUtils.getEmpId().toString());
			delegate.setAgentUserId(agentUserId);
			delegate.setStartDate(sdf.parse(startDateStr));
			delegate.setEndDate(endDate);
			delegate.setIsEnabled(option);
			delegateMappingService.save(delegate);
		}else{
			delegate.setUserId(ShiroUtils.getEmpId().toString());
			delegate.setAgentUserId(agentUserId);
			delegate.setStartDate(sdf.parse(startDateStr));
			delegate.setEndDate(endDate);
			delegate.setIsEnabled(option);
			delegateMappingService.update(delegate);
		}

        return R.ok();
    }

}
